package org.odefu.model.project;

import com.google.gwt.json.client.JSONArray;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONString;
import com.google.gwt.json.client.JSONValue;

public final class ProjectFactory
{
	private static final String NAME = "name";
	private static final String TABLES = "tables";

	private ProjectFactory()
	{
	}

	public static Project create(final String data)
	{
		final JSONValue json = JSONParser.parseStrict(data);
		if (json != null)
		{
			return create(json.isObject());
		}
		throw new RuntimeException("Invalid JSON string: " + data);
	}

	private static Project create(final JSONObject obj)
	{
		assert obj != null : "JSON object is null.";

		final Project project = new Project(parseName(obj));
		createTables(project, obj.get(TABLES));
		return project;
	}

	private static void createTables(final Project project, final JSONValue tablesValue)
	{
		if (tablesValue == null)
		{
			// It's ok not to have any tables defined
			return;
		}

		final JSONArray tables = tablesValue.isArray();
		if (tables == null)
		{
			throw new IllegalArgumentException("The tables value is not an array.");
		}

		for (int i = 0; i < tables.size(); i++)
		{
			final JSONValue tableValue = tables.get(i);
			final JSONObject table = tableValue.isObject();
			if (table == null)
			{
				throw new RuntimeException("Invalid JSON data for table: " + tableValue.toString());
			}
			project.createTable(parseName(table));
		}
	}

	private static String parseName(final JSONObject obj)
	{
		final JSONString str = parseString(obj, NAME);
		assert str != null : "JSON object doesn't have a name property.";
		return str.stringValue();
	}

	private static JSONString parseString(final JSONObject obj, final String key)
	{
		final JSONValue value = obj.get(key);
		assert value != null : "JSON object doesn't have value for key: " + key;
		return value.isString();
	}
}
